using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;

namespace Speedball2 {
  public static class BankManager {
    //private static VersionEnum _version;
    private static Dictionary<int, Bank> _banks;
    private static Dictionary<int, Bitmap> _bitmaps;
    private static Dictionary<int, Bitmap> _bitmapsBlue;

    static BankManager () {
    }

    public static void Init (Palette paletteMenu, Palette paletteManager, Palette paletteMatch, Palette paletteMatchBlue) {
      if (!Directory.Exists (Game.BaseFolder))
        Directory.CreateDirectory (Game.BaseFolder);

      _banks = new Dictionary<int, Bank> ();

      //Palette paletteIntro;
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x8E3C, 28495), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (-1, new Bank ("doors.pc1", pc1));
      //  paletteIntro = pc1._palette;
      //}
      //_banks.Add (-2, new Bank ("logofont.spr", Game.Disk.Extract (0xFD8C, 5632), 16, 16, paletteIntro, null, Sprite.MasksEnum.Transparent));

      _banks.Add (0x1602A, new Bank ("status.dat", Game.Disk.Extract (0x6322A, 2560), 320, 16, paletteMatch, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x16A2A, new Bank ("digits.spr", Game.Disk.Extract (0x63C2A, 320), 8, 8, paletteMatch, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x16B6A, new Bank ("diamond.dat", Game.Disk.Extract (0x63D6A, 9216), 96, 64, paletteMatch, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x18F6A, new Bank ("dmndfont.spr", Game.Disk.Extract (0x6616A, 1152), 8, 8, paletteMatch, null, Sprite.MasksEnum.Opaque));

      _banks.Add (0x193EA, new Bank ("balls.spr", Game.Disk.Extract (0x9E400, 4480), 16, 16, paletteMatch, null, Sprite.MasksEnum.Transparent));
      // need opaque for some sprites...
      //_banks.Add (0x1A56A, new Bank ("balls_A2.spr", Game.Disk.Extract (0x9F580, 7040), 16, 16, paletteMatch, null, Sprite.MasksEnum.Opaque));
      _banks [0x193EA].AddToBank ("balls.spr", Game.Disk.Extract (0x9F580, 7040), 16, 16, paletteMatch, null, Sprite.MasksEnum.Opaque);
      //_banks.Add (0x1C0EA, new Bank ("balls_B_players_medics_bigball_deck.spr", Game.Disk.Extract (0xA1100, 75264), 32, 32, paletteMatch, paletteMatchBlue, Sprite.MasksEnum.Transparent));
      _banks [0x193EA].AddToBank ("balls.spr", Game.Disk.Extract (0xA1100, 75264), 32, 32, paletteMatch, paletteMatchBlue, Sprite.MasksEnum.Transparent);

      // MENU
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x66A00, 22469), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (0x2E7EA, new Bank ("border.pc1", pc1));
      //}

      _banks.Add (0x33FB0, new Bank ("blocks.dat", Game.Disk.Extract (0x6C1C6, 22144), 16, 16, paletteManager, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x39630, new Bank ("leagfont.spr", Game.Disk.Extract (0x71846, 1632), 8, 8, paletteMenu, null, Sprite.MasksEnum.Transparent));
      _banks.Add (0x39C90, new Bank ("bigfont.spr", Game.Disk.Extract (0x71EA6, 4864), 16, 16, paletteMenu, null, Sprite.MasksEnum.Transparent));
      _banks.Add (0x3AF90, new Bank ("small1.spr", Game.Disk.Extract (0x731A6, 928), 8, 8, paletteMenu, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x3B330, new Bank ("small2.spr", Game.Disk.Extract (0x73546, 1024), 8, 8, paletteMenu, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x3B730, new Bank ("mngrfont.spr", Game.Disk.Extract (0x73946, 576), 8, 8, paletteManager, null, Sprite.MasksEnum.Opaque));
      //_banks.Add (0x3B970, new Bank ("unkfont.spr", Game.Disk.Extract (0x73B86, 864), 8, 8, paletteManager, null, Sprite.MasksEnum.Transparent));
      _banks.Add (0x3BCD0, new Bank ("cashfont.spr", Game.Disk.Extract (0x73EE6, 320), 8, 8, paletteManager, null, Sprite.MasksEnum.Transparent));
      _banks.Add (0x3BE10, new Bank ("tinyfont.spr", Game.Disk.Extract (0x74026, 1184), 8, 8, paletteManager, null, Sprite.MasksEnum.Transparent));
      // depends on palette (match won, match lost):
      //_banks.Add (0x3C2B0, new Bank ("lastfont.spr", Game.Disk.Extract (0x744C6, 1152), 8, 8, paletteManager, Sprite.MasksEnum.Transparent));
      _banks.Add (0x3C730, new Bank ("mid.spr", Game.Disk.Extract (0x74946, 2048), 16, 16, paletteManager, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x3CF30, new Bank ("botleft.spr", Game.Disk.Extract (0x75146, 22528), 32, 32, paletteManager, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x42730, new Bank ("armor.spr", Game.Disk.Extract (0x7A946, 18944), 32, 32, paletteManager, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x47130, new Bank ("heads.spr", Game.Disk.Extract (0x7F346, 34560), 16, 16, paletteManager, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x4F830, new Bank ("groups.spr", Game.Disk.Extract (0x87A46, 5760), 16, 16, paletteManager, null, Sprite.MasksEnum.Opaque));

      //Palette paletteReward;
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x890C6, 20738), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (0x50EB0, new Bank ("reward.pc1", pc1));
      //  paletteReward = pc1._palette;
      //}
      //Palette paletteDefeat;
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x8E1C8, 16904), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (0x55FB2, new Bank ("defeat.pc1", pc1));
      //  paletteDefeat = pc1._palette;
      //}
      //_banks.Add (0x3C2B0, new Bank ("lastfont.spr", Game.Disk.Extract (0x744C6, 1152), 8, 8, paletteReward, null, Sprite.MasksEnum.Transparent));
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x923D0, 12213), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (0x5A1BA, new Bank ("victory1.pc1", pc1));
      //}
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x95386, 12230), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (0x5D170, new Bank ("victory2.pc1", pc1));
      //}
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x9834C, 12249), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (0x60136, new Bank ("victory3.pc1", pc1));
      //}
      //using (Pc1 pc1 = new Pc1 (Game.Disk.Extract (0x9B326, 12212), Sprite.MasksEnum.Opaque)) {
      //  _banks.Add (0x63110, new Bank ("victory4.pc1", pc1));
      //}

      _banks.Add (0x537EA, new Bank ("terrain.spr", Game.Disk.Extract (0xB3800, 4608), 32, 32, paletteMatch, null, Sprite.MasksEnum.Opaque));
      // top (&mirrored for bottom)
      _banks.Add (-3, new Bank ("pitch.dat", Game.Disk.Extract (0xB4A00, 10240), 640, 32, paletteMatch, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x549EA, new Bank ("wall_L.dat", Game.Disk.Extract (0xB7200, 7168), 32, 32, paletteMatch, null, Sprite.MasksEnum.Opaque));
      _banks.Add (0x565EA, new Bank ("wall_R.dat", Game.Disk.Extract (0xB8E00, 7168), 32, 32, paletteMatch, null, Sprite.MasksEnum.Opaque));

      _bitmaps = new Dictionary<int, Bitmap> ();
      _bitmapsBlue = new Dictionary<int, Bitmap> ();
      int total = 0;
      foreach (KeyValuePair<int, Bank> kvp in _banks) {
        int bankAddress = kvp.Key;
        if (bankAddress < 0)
          continue;
        Bank bank = kvp.Value;
        int address = bankAddress;
        for (int i = 0; i < bank.NbBitmaps; i++) {
          //int address = bankAddress + i * size.Width * size.Height / 2;
          //if (address == 0x3BE10) {
          //  int j = 0;
          //}
          _bitmaps.Add (address, bank.GetBitmap (i));
          _bitmapsBlue.Add (address, bank.GetBitmap (i, SideEnum.Blue_1));
          Size size = bank.GetSize (i);
          address += size.Width * size.Height / 2;
        }
        Console.WriteLine ("{0}: {1}", bank._filename, bank.NbBitmaps);
        total += bank.NbBitmaps;
      }
      Console.WriteLine ("Total: {0}", total);

      //files.Add ("doors.pc1", Game.Disk.Extract (0x8E3C, 28495));
      //files.Add ("logofont.spr", Game.Disk.Extract (0xFD8C, 5632));
      //files.Add ("status.dat", Game.Disk.Extract (0x6322A, 2560));
      //files.Add ("digits.spr", Game.Disk.Extract (0x63C2A, 320));

      //files.Add ("doors.pc1", Game.Disk.Extract (0x8E3C, 28495));
      //files.Add ("logofont.spr", Game.Disk.Extract (0xFD8C, 5632));
      //files.Add ("status.dat", Game.Disk.Extract (0x6322A, 2560));
      //files.Add ("digits.spr", Game.Disk.Extract (0x63C2A, 320));

    }

    public static Bitmap GetBitmap (int address) {
      return (_bitmaps [address]);
    }

    public static Bitmap GetBitmap (int address, bool side) {
      if (side)
        return (_bitmapsBlue [address]);
      else
        return (_bitmaps [address]);
    }

    public static Dictionary<int, Bank> Banks {
      get {
        return (_banks);
      }
    }
  }

  public enum BankEnum {
    status_dat,
    digits_spr,
    diamond_dat,
    dmndfont_spr,
    unk01,
    border_pc1,
    blocks_dat = 0x33FB0,
    leagfont_spr = 0x39630,
    bigfont_spr = 0x39C90,
    small1_spr = 0x3AF90,
    small2_spr = 0x3B330,
    mngrfont_spr = 0x3B730,
    unkfont_spr = 0x3B970,
    cashfont_spr = 0x3BCD0,
    tinyfont_spr = 0x3BE10,
    lastfont_spr = 0x3C2B0,
    unk03,
    reward_pc1,
    defeat_pc1,
    victory1_pc1,
    victory2_pc1,
    victory3_pc1,
    victory4_pc1,
    unk04,
    unk05,
    pitch_dat,
    wallL,
    wallR
  }
}
